package com.pentofab.payrollmanagement.ui.controller;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;

import com.pentofab.payrollmanagement.application.PayrollApplicationFactory;
import com.pentofab.payrollmanagement.dao.EmployeeDao;
import com.pentofab.payrollmanagement.dao.model.Company;
import com.pentofab.payrollmanagement.dao.model.Department;
import com.pentofab.payrollmanagement.dao.model.Designation;
import com.pentofab.payrollmanagement.dao.model.EmpCategory;
import com.pentofab.payrollmanagement.dao.model.Employee;
import com.pentofab.payrollmanagement.dao.model.EmployeeDetail;
import com.pentofab.payrollmanagement.dao.model.Units;
import com.pentofab.payrollmanagement.dao.model.UserAccounts;
import com.pentofab.payrollmanagement.database.impl.EmployeeRepositoryImpl;
import com.pentofab.payrollmanagement.database.impl.EmployeeTableSQLConstants;
import com.pentofab.payrollmanagement.exception.BusinessException;
import com.pentofab.payrollmanagement.utilities.PayRollUtility;

public class CompanyEmployeesTabController extends AbstractUIController
implements Initializable {

	@FXML
	Parent root;
	@FXML
	private TableView<EmployeeDetail> tableView;
	@FXML 
	private TableColumn<EmployeeDetail, String> DOB;
	@FXML 
	private TableColumn<EmployeeDetail, String> DOJ;
	@FXML 
	private TableColumn<EmployeeDetail, String> company;
	@FXML 
	private TableColumn<EmployeeDetail, String> createdBy;
	@FXML 
	private TableColumn<EmployeeDetail, String> deletedBy;
	@FXML 
	private TableColumn<EmployeeDetail, String> deletionDate;
	@FXML 
	private TableColumn<EmployeeDetail, String> department;
	@FXML 
	private TableColumn<EmployeeDetail, String> designation;
	@FXML 
	private TableColumn<EmployeeDetail, String> epId;
	@FXML 
	private TableColumn<EmployeeDetail, String> modifiedBy;
	@FXML 
	private TableColumn<EmployeeDetail, String> name;
	@FXML 
	private TableColumn<EmployeeDetail, String> unit;


	@FXML
	TextField importFileLoc;
	@FXML
	TextField exportFileLoc;
	@FXML
	TextField employeeIdList;

	private Company curCompany;
	private UserAccounts userAccounts;
	private EmployeeDao employeeDao =  PayrollApplicationFactory.getEmployeeMgmt();

	@Override
	public Parent getView() {
		return root;
	}

	@Override
	public String getTitle() {

		return null;
	}


	@Override
	public void refreshUI(Object... args) {

		importFileLoc.clear();
		exportFileLoc.clear();
		employeeIdList.clear();

		if (args != null && args.length > 0) {
			Company company = (Company) args[0];
			this.curCompany = company;

			if(args.length > 1 && args[1] instanceof UserAccounts){
				this.userAccounts = (UserAccounts) args[1];
			}
		}
		populateUserAccountsTable(this.curCompany.getCompanyID());

	}

	public void add() {
		PayrollApplicationFactory.getMainController().showScreen(
				MainController.ADD_EMPLOYEE_SCREEN, true, this.curCompany,this.userAccounts);
	}


	public void edit() {

		if(tableView.getSelectionModel().getSelectedIndex() < 0){
			showError("Select an employee to delete.");
			return;
		}


		EmployeeDetail employeeDetail = this.tableView.getSelectionModel().getSelectedItem();
		Employee employee = null;  
		try {

			employee = employeeDao.getEmpById(employeeDetail.getEpId());
			System.out.println("employee :123 "+employee);
		} catch (BusinessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		if (employee != null) {

			PayrollApplicationFactory.getMainController().showScreen(
					MainController.ADD_EMPLOYEE_SCREEN, true, this.curCompany,
					employee,this.userAccounts);
		}else {
			showError("Select an employee to edit");
		}
	}

	public void deleteEmployee() {

		if(tableView.getSelectionModel().getSelectedIndex() < 0){
			showError("Select an employee to delete.");
			return;
		}

		EmployeeDetail employeeDetail = this.tableView.getSelectionModel().getSelectedItem();

		if (employeeDetail != null) {

			if(showConfirmDialog("Delete employee : "+employeeDetail.getEpId())){
				try {

					employeeDao.deleteEmployee(employeeDetail.getEpId(),userAccounts.getUsername());
				} catch (Exception e) {

					e.printStackTrace();

					showError(String.format(UIMessages.FAILED_TO_DELETE_EMPLOYEE, employeeDetail.getEpId()));
					return;
				}
				showInfo(String.format(UIMessages.EMPLOYEE_DELETION_SUCCESS,employeeDetail.getEpId()));
				refreshUI(this.curCompany,this.userAccounts);
			}
		} else {
			showError("Select an employee to edit");
		}

	}

	public void goBack() {

		PayrollApplicationFactory.getMainController().showScreen(
				MainController.COMPANIES_LIST_SCREEN, false, userAccounts);
	}
	@Override
	public void initialize(URL arg0, ResourceBundle arg1) {
		iniTableProps();

	}

	private void iniTableProps() {

		epId.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("epId"));
		name.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("name"));
		DOB.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("DOB"));
		DOJ.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("DOJ"));
		company.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("company"));
		department.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("department"));
		designation.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("designation"));
		createdBy.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("createdBy"));
		modifiedBy.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("modifiedBy"));
		deletedBy.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("deletedBy"));
		deletionDate.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("deletionDate"));
		unit.setCellValueFactory(new PropertyValueFactory<EmployeeDetail, String>("unit"));

	}

	private void populateUserAccountsTable(String company){

		tableView.setEditable(false);
		tableView.getItems().clear();
		ObservableList<EmployeeDetail> data = FXCollections.observableArrayList();
		PayRollUtility.debug("===================== populate employees table start =====================");

		data.clear();
		try {
			ArrayList<Employee> empList = employeeDao.getAllCompanyEmployees(company);
			System.out.println("empList : " + empList);
			if(empList == null){
				return;
			}
			data.addAll(EmployeeDetail.getEmployeeDetail(empList));
		} catch (Exception e) {
			e.printStackTrace();
		}
		PayRollUtility.debug("data  : " + data);
		tableView.setItems(data);

		PayRollUtility.debug("===================== populate employees table end =====================");



	}


	public void browseImport(){

		try{
			FileChooser fileChooser = new FileChooser(); 
			fileChooser.setTitle("Select Employee File");

			File file = fileChooser.showOpenDialog(null);
			File destinationFile = new File(file.getAbsolutePath());
			String fileName = destinationFile.getName();
			if(file!=null && !file.isDirectory()){

				importFileLoc.setText(destinationFile.getAbsolutePath());
				if(fileName !=null && !fileName.equals(UIMessages.FileName.EMP_LIST)){
					showError("To import Employee, Please select file having name  :"+UIMessages.FileName.EMP_LIST);
					refreshUI();
					return;
				}


				FileReader fr = new FileReader(file);

				BufferedReader br = new BufferedReader(fr);

				String colnms = br.readLine();
				if(colnms == null || colnms.equals("")){

					showError("No data in file : "+fileName);
					refreshUI();
					br.close();
					return;
				}


				String[] colArray = colnms.split(",");
				if(colArray == null || colArray.length != 21	){

					showError("Improper data in file : "+fileName+", Valid data must contain only \n"
							+ "EmployeeId,Name,Telophone1,Telophone2,Address1,Address2,\nCity,State,Country,Zipcode,CompanyCode,Unit\n,DeptCode,DesignationCode,"
							+ "Category,sex,DOJ\n,hoursperday,rools,DOB,weeklyoff\n fields");
					br.close();
					refreshUI();
					return;
				}
				br.close();

			}else{
				showInfo("Import Operation cancelled as file not selected for import.");
				refreshUI();
				return;
			}

		}catch(Exception e){
			refreshUI();
			showError("Error while importing Employee data.");
		}
	}

	public void importSubmit(){

		try{

			File file = new File(importFileLoc.getText().trim());
			ArrayList<HashMap<String, String>> employeeInfo = new ArrayList<HashMap<String,String>>();
			FileReader fr = new FileReader(file);
			BufferedReader br = new BufferedReader(fr);
			String[] clnmsArray = br.readLine().split(",");
			String dataLine = null;
			while((dataLine = br.readLine()) != null){
				System.out.println("dataLine : "+dataLine);
				String[] data = dataLine.split(",");

				HashMap<String, String> cur = new HashMap<String, String>();
				for(int i= 0;i < data.length;i++){

					cur.put(clnmsArray[i],data[i].replaceAll("'", ""));
				}
				System.out.println("cur : "+cur);
				employeeInfo.add(cur);

			}

			System.out.println("companyInfoMap : "+employeeInfo.size());
			Iterator<HashMap<String, String>> companyInfoMapIterator = employeeInfo.iterator();
			StringBuffer errorBuffer = new StringBuffer();
			while(companyInfoMapIterator.hasNext()){
				try{

				HashMap<String, String > current = companyInfoMapIterator.next();
					boolean updateNextEmp = true;
					Employee employee = new Employee();

					if(current.get("EmployeeId").trim().equals("")){

						String empId = current.get("CompanyCode")+employeeDao.getNextEmpID(current.get("CompanyCode"));
						employee.setEmpId(empId);
					}else{
						updateNextEmp = false;
						employee.setEmpId(current.get("EmployeeId"));
					}
					employee.setEmpName(current.get("Name"));
					employee.setTelophone1(current.get("Telophone1"));
					employee.setTelophone2(current.get("Telophone2"));
					employee.setAddress1(current.get("Address1"));
					employee.setAddress2(current.get("Address2"));
					employee.setCity(current.get("City"));
					employee.setState(current.get("State"));
					employee.setCountry(current.get("Country"));
					employee.setZipCode(current.get("Zipcode"));
					employee.setDOJ(current.get("DOJ"));
					employee.setDOB(current.get("DOB"));
					employee.setHoursperday(current.get("hoursperday"));
					employee.setWeeklyOff(current.get("weeklyoff"));
					employee.setCreatedby(userAccounts.getUsername());
					employee.setModifiedBy(userAccounts.getUsername());
					Department dept = new Department();
					dept.setCode(current.get("DeptCode"));
					employee.setDepertment(dept);
					Designation desgn =new Designation();
					desgn.setCode(current.get("DesignationCode"));
					employee.setDesignation(desgn);
					employee.setUnit(current.get("Unit"));
					EmpCategory category = new EmpCategory();
					category.setCode(current.get("Category"));
					employee.setCategory(category);

					if (current.get("Sex").trim().equals("1")) {
						employee.setSex("M");
					} else {
						employee.setSex("F");
					}

					employee.setCompany(employeeDao.getCompany(current.get("CompanyCode")));

					if(current.get("rools").equals("0")){

						employee.setRools(true);
					}else{
						employee.setRools(false);
					}
					employeeDao.addEmploye(employee, updateNextEmp);
				}catch(Exception e){
					e.printStackTrace();
					errorBuffer.append(/*"Name :"+current.get("Name")+"\n"*/"");
				}
			}

			if(!errorBuffer.toString().equals("")){
				showError("Failed to add following Employees due to data error,\n1. Units with code may already exists\n"
						+ "2. Parent copany may not be present.\n"+errorBuffer);
			}

			refreshUI();
			br.close();
		}catch(Exception e){
			e.printStackTrace();
			refreshUI();
			showError("Error while importing company data.");
		}

	}

	public void browseExport(){


		if(employeeIdList.getText().trim().equals("")){

			showError("Please select ids seprated by',' to export.");
			return;
		}

		try{
			DirectoryChooser fileChooser = new DirectoryChooser(); 
			fileChooser.setTitle("Select Destination");

			File file = fileChooser.showDialog(null);
			File destinationFile = new File(file.getAbsolutePath());
			if(file!=null && file.isDirectory()){

				exportFileLoc.setText(destinationFile.getAbsolutePath());

			}else{
				showInfo("Export Operation cancelled as Directory nor selected for export.");
				refreshUI();
				return;
			}

		}catch(Exception e){
			refreshUI();
			showError("Error while exporting Employee data.");
		}

	}
	public void exportSubmit(){
		try{

			if(employeeIdList.getText().trim().equals("")){

				showError("Please select ids seprated by',' to export.");
				return;
			}

			String selectedCodes = employeeIdList.getText().trim();
			String[] codesArray = selectedCodes.split(",");
			File file = new File(exportFileLoc.getText()+"//"+UIMessages.FileName.EMP_LIST);
			FileWriter fw =new FileWriter(file,true);
			BufferedWriter bw =new BufferedWriter(fw);
			bw.write("EmployeeId,Name,Telophone1,Telophone2,Address1,Address2,City,State,Country,Zipcode,CompanyCode,Unit,DeptCode,"
					+ "DesignationCode,Category,sex,DOJ,hoursperday,rools,DOB,weeklyoff\n");

			for(int i=0; i < codesArray.length;i++){


				Employee emp = employeeDao.getEmpById(codesArray[i]);

				StringBuffer dataLine = new StringBuffer();
				dataLine.append(emp.getEmpId()).append(",");
				dataLine.append(emp.getEmpName()).append(",");
				dataLine.append(emp.getTelophone1()).append(",");
				dataLine.append(emp.getTelophone2()).append(",");
				dataLine.append(emp.getAddress1()).append(",");
				dataLine.append(emp.getAddress2()).append(",");
				dataLine.append(emp.getCity()).append(",");
				dataLine.append(emp.getState()).append(",");
				dataLine.append(emp.getCountry()).append(",");
				dataLine.append(emp.getZipCode()).append(",");
				dataLine.append(emp.getCompany().getCompanyID()).append(",");
				dataLine.append(emp.getUnit()).append(",");
				dataLine.append(emp.getDepertment().getCode()).append(",");
				dataLine.append(emp.getDesignation().getCode()).append(",");
				dataLine.append(emp.getCategory().getCode()).append(",");
				dataLine.append(emp.getSex()).append(",");
				dataLine.append(emp.getDOJ()).append(",");
				dataLine.append(emp.getHoursperday()).append(",");
				boolean rools =emp.isRools();
				
				if(rools){
					dataLine.append("0").append(",");
				}else{
					dataLine.append("1").append(",");
				}
				dataLine.append(emp.getDOB()).append(",");
				dataLine.append(emp.getWeeklyOff());


				bw.write(dataLine.toString()+"\n");
			}

			showInfo("Successfuly exported Employees.");
			bw.flush();
			fw.flush();
			bw.close();
			fw.close();

		}catch(Exception e){
			e.printStackTrace();
			showError("Error while exporting company data.");
		}
		refreshUI();

	}
}
